#include "spdlog/spdlog.h"

#include <memory>
#include <fstream>
#include <boost/shared_ptr.hpp>
#include "json/json.h"

#include "http_server_base.hpp"
#include "http_server_session.hpp"

using namespace mms;

HttpServerBase::~HttpServerBase()
{
}

bool HttpServerBase::start(uint16_t port, std::string addr)
{
    if(!register_route()){
        spdlog::error("http server base register router failed, port:{}", port);
        return false;
    }
    if(0 == start_listen(port,addr)){
        return true;
    }
    return false;
}

void HttpServerBase::stop()
{
    stop_listen();
}

bool HttpServerBase::on_get(const std::string& path, const HTTP_HANDLER& handler)
{
    return get_route_tree_.add_route(path,handler);
}

bool HttpServerBase::on_post(const std::string& path, const HTTP_HANDLER& handler)
{
    return post_route_tree_.add_route(path,handler);
}

bool HttpServerBase::register_route()
{
    return true;
}

void HttpServerBase::on_tcp_socket_open(std::shared_ptr<TcpSocket> sock)
{
    auto http_conn = std::static_pointer_cast<HttpConn>(sock);
    std::shared_ptr<HttpServerSession<HttpConn>> s = 
        std::make_shared<HttpServerSession<HttpConn>>(this,http_conn);
    http_conn->set_session(s);
    s->service();
}

void HttpServerBase::on_tcp_socket_close(std::shared_ptr<TcpSocket> sock)
{
    auto http_conn = std::static_pointer_cast<HttpConn>(sock);
    std::shared_ptr<HttpServerSession<HttpConn>> s = 
        std::static_pointer_cast<HttpServerSession<HttpConn>>(http_conn->get_session());
        http_conn->clear_session();
        if(s){
            s->close();
        }
}

boost::asio::awaitable<bool> HttpServerBase::on_new_request(std::shared_ptr<HttpServerSession<HttpConn>> session, std::shared_ptr<HttpRequest> req, std::shared_ptr<HttpResponse> resp)
{
    spdlog::info("get new http request, path: {}", req->get_path());
    auto tcpsock = std::static_pointer_cast<TcpSocket> (resp->get_conn());
    auto addr = tcpsock->get_sock().remote_endpoint().address().to_string();
    auto port = tcpsock->get_sock().remote_endpoint().port();
    
    auto user = req->get_query_param("user");
    auto pwd = req->get_query_param("password");
    if(user != "dxz" || pwd != "123456"){
        resp->add_header("Content-Type", "application/json");
        resp->add_header("Connection", "keep=alive");
        resp->add_header("Content-Length", std::to_string(9999999999999999));
        Json::Value root;
        root["code"] = 0;
        root["app"] = 0;
        root["stream"] = 0;
        std::string body = root.toStyledString();
       // resp->add_header("Content-Type", "application/json");
        spdlog::warn("get a warning http request");
        spdlog::warn("remote addr:{} port:{}, user = {}, pwd = {}", 
         addr, port, user, pwd);
        //co_await resp->write_header(200, "OK");
        //co_await resp->write_data((const uint8_t*)(body.data()), body.size());
        resp->close();
        co_return false;
    }
    spdlog::info("remote addr:{} port:{}", addr, port);
    switch (req->get_method())
    {
        case GET:{
            auto handler = get_route_tree_.get_route(req->get_path(),req->path_params());
            if (!handler.has_value()) {
                resp->add_header("Connection", "close");
                co_await resp->write_header(404, "Not found");
                resp->close();
            }else{
                co_await handler.value()(session,req,resp);
                // resp->close(); // 相应玩就关闭连接
            }
            break;
        }
        case POST: {
            auto handler = post_route_tree_.get_route(req->get_path(), req->path_params());
            if (!handler.has_value()) {//404
                resp->add_header("Connection", "close");
                co_await resp->write_header(404, "Not Found");
                resp->close();
            }
            else {
                co_await handler.value()(session, req, resp);
                // resp->close(); // 相应玩就关闭连接
            }
            break;
        }
    }
    co_return true;
}
